package picasa;
import java.awt.Image;
import java.awt.Toolkit;
import java.awt.color.ColorSpace;
import java.awt.geom.AffineTransform;
import java.awt.image.*;
import java.io.File;
import java.util.*;

import javax.imageio.ImageIO;

public class EditFunctions {
	
	static File outputFile = new File("C://workspace//Picasa//ImageLibraries//Farzana//IMG_1882.JPG");
	static File tempFile = new File("C://workspace//Picasa//ImageLibraries//Farzana//IMG_1882_1.JPG");
	static File originalFile = new File("C://workspace//Picasa//ImageLibraries//Farzana//IMG_1882_original.JPG");
	static ArrayList historyArray = new ArrayList();
	
	
	private boolean isOriginal;
	
	
	
	public void setIsOriginal(boolean b){
		this.isOriginal=b;
	}
	/*convert to gray scale*/
	public void grayScale(BufferedImage newImage){
		
		//save the original image without any changes made to it, just give it a different name
		renameImage(newImage,1);
		
		
		//saveImage(newImage);
		historyArray.add("bw");
		ColorConvertOp op = new ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY),null);
		newImage = op.filter(newImage, null);
		saveImage(newImage);
		newImage.flush();
		
	}
	
	public void colorTint (BufferedImage bimage, String color){
		
		renameImage(bimage,1);
		historyArray.add("color");
		Image Iimage = bimage;
		Iimage = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(Iimage.getSource(), new ColorFilter(color)));
		bimage = Conversion.convertToBufferedImage(Iimage,bimage.getWidth(), bimage.getHeight(),BufferedImage.TYPE_INT_RGB);
		saveImage(bimage);
		bimage.flush();
	}
	
	public void sepia(BufferedImage bimage){
		
		renameImage(bimage,1);
		historyArray.add("sepia");
		Image image = bimage;
		ImageFilter filter = new SepiaFilter();
	    image = Toolkit.getDefaultToolkit().createImage
	     (new FilteredImageSource(image.getSource(), filter));
	  
	    bimage = Conversion.convertToBufferedImage(image,bimage.getWidth(), bimage.getHeight(),BufferedImage.TYPE_INT_RGB);
	    saveImage(bimage);
	    bimage.flush();
		
		
	}
	public void crop (BufferedImage newImage, int x, int y, int w, int h){
		renameImage(newImage,1);
		historyArray.add("crop");
		newImage = newImage.getSubimage(x,y,w,h);
		saveImage(newImage);
		
	}
	
	public void blurImage(BufferedImage newImage){
		try{
			
			// saveImage(newImage);
			historyArray.add("blur");
			float data[] = {  0.1111f, 0.1111f, 0.0111f, 0.1111f , 0.1111f, 0.1111f, 0.1111f, 0.1111f, 0.1111f  };
			Kernel kernel = new Kernel(3 , 3, data);
			ConvolveOp convolve = new ConvolveOp(kernel,  ConvolveOp.EDGE_NO_OP, null);
			BufferedImage bImage = newImage;
			bImage = convolve.filter(newImage, bImage);
			saveImage(bImage);
			bImage.flush();
		}
		catch(Exception e){}
	}
	public void rotateImage(BufferedImage newImage, double rotationAngle){
		renameImage(newImage,1);
		historyArray.add("rotate");
		
        AffineTransform atx = new AffineTransform();
  		atx.rotate(Math.toRadians(90), newImage.getWidth()/2, newImage.getHeight()/2);
  		AffineTransformOp op = new AffineTransformOp(atx, AffineTransformOp.TYPE_BILINEAR);
  		newImage = op.filter(newImage, null);
		saveImage(newImage);
		
	}
	
	
	
	public void sharpenImage(BufferedImage newImage){
		try{
			
			
			BufferedImage bi = ImageIO.read(outputFile);
			if(isOriginal == true)
				saveImage(newImage);
			
			renameImage(newImage,1);
			historyArray.add("sharpen");
			float data[] = { 0.f, -.25f,  0.f, -.25f,  2.f, -.25f, 0.f,  -.25f,  0.f};
			Kernel kernel = new Kernel(3 , 3, data);
			ConvolveOp convolve = new ConvolveOp(kernel,  ConvolveOp.EDGE_NO_OP, null);
			bi = convolve.filter(newImage,bi);
			saveImage(bi);
			bi.flush();
			
			
		}
		catch(Exception e){
			
			System.out.println("Exception with sharpen image: " + e.toString());
		}
		
	}
	
	public void invertImage(BufferedImage newImage){
		renameImage(newImage,1);
		historyArray.add("emboss");
		BufferedImage bi = null;
		byte lut[]= new byte[256];
		for (int j=0; j < 256; j++) lut[j] = (byte) (256-j);
		LookupOp invert = new LookupOp(new ByteLookupTable(0,lut),null);
		bi = invert.filter(newImage,bi);
		saveImage(bi);
		bi.flush();
	}
	
	
	
	
	public  void EmbossImage(BufferedImage newImage){
		
		
		renameImage(newImage,1);
		int width = newImage.getWidth ();
		int height = newImage.getHeight ();
		
		//saveImage(newImage);
		historyArray.add("emboss");
		BufferedImage dst =
			new BufferedImage (width, height,
					BufferedImage.TYPE_INT_RGB);
		
		for (int i = 0; i < height; i++)
			for (int j = 0; j < width; j++)
			{
				int current = newImage.getRGB (j, i);
				
				int upperLeft = 0;
				if (i > 0 && j > 0)
					upperLeft = newImage.getRGB (j - 1,
							i - 1);
				
				int rDiff = ((current >> 16) & 255) -
				((upperLeft >> 16) & 255);
				int gDiff = ((current >> 8) & 255) -
				((upperLeft >> 8) & 255);
				int bDiff = (current & 255) -
				(upperLeft & 255);
				
				int diff = rDiff;
				if (Math.abs (gDiff) > Math.abs (diff))
					diff = gDiff;
				if (Math.abs (bDiff) > Math.abs (diff))
					diff = bDiff;
				
				int grayLevel =
					Math.max (Math.min (128 + diff, 255),
							0);
				dst.setRGB (j, i,
						(grayLevel << 16) +
						(grayLevel << 8) +
						grayLevel);
			}
		
		saveImage(dst);
		dst.flush();
	}
	
	 
	public void saveImage(BufferedImage newImage){
		try{
			
			
	
	
			//System.out.println("isOriginal is: " isOriginal);
			if(isOriginal==true){
				
	
				outputFile.renameTo(originalFile);
				isOriginal=false;
			}else{
				
			
				
				ImageIO.write(newImage, "jpeg", outputFile);	
			}
	
			//System.out.println(time2 - time1 + " :Time to Save Image");
		}
		catch(Exception e){}
	}
	
	public void renameImage(BufferedImage newImage, int i){
		try{
			
			ImageIO.write(newImage, "jpeg", tempFile);
			
			
			
		}
		catch(Exception e){
			
			System.out.println("Exception in renameImage: " + e.toString());
		}
	}
	
	//saves the final image and deletes all temporary images
	public void finalSave(){
		
		if(tempFile.exists())
			tempFile.delete();
		if(originalFile.exists())
			originalFile.delete();
		
		isOriginal = true;
	}
	
	//can only go back one step
	public void undo(){
		
		if(!(isOriginal)){
			if(tempFile.exists()){
				if (outputFile.exists())
					outputFile.delete();
				
				tempFile.renameTo(outputFile);
			}
		}
	}
	//goes bact to original image
	public void backToOrigImage (BufferedImage newImage){
		try{
			
	
			
			if (historyArray.size()!=0){
				if(outputFile.exists())
					outputFile.delete();
				if(originalFile.exists())
					originalFile.renameTo(outputFile);
				
				historyArray.clear();
				
				//delete temp image
				if(tempFile.exists())
					tempFile.delete();
				
			}
	
			
			//System.out.println(t2-t1 + " :undo time in nanosecond");
		}catch (Exception e){
			
			System.out.println("Exception in undo " + e.toString());
		}
		
	}
	
}
